package rad.framework.seam;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import rad.framework.lang.ReflectionUtil;

/**
 * The StatusMachine is a state machine that is focused on changing the status
 * of an entity over its lifecycle. The status/state is stored in the entity.
 * The actions are implemented by the editor, service, and/or bpm. This class
 * just stores the metadata on what actions are available for which
 * statuses/states. The actual status of the entity is determined and updated by
 * the action methods.
 * 
 * @author boudyacho
 */
public class StatusMachine implements Serializable {

	protected Map<Object, List<ActionMetadata>> statusMachine = new HashMap<Object, List<ActionMetadata>>();

	private Map<String, ActionMetadata> actions = new HashMap<String, ActionMetadata>();

	public StatusMachine(Object entity) {
		List<Method> methods = ReflectionUtil.findMethodsByAnnotation(entity.getClass(), Action.class);
		int sort = 1;
		for (Method method : methods) {
			Action annotation = method.getAnnotation(Action.class);
			ActionMetadata action = new ActionMetadata(method, annotation,
					sort++, entity.getClass().getSimpleName());
			actions.put(method.getName(), action);
		}
	}

	@SuppressWarnings("unchecked")
	public List<ActionMetadata> getStatusActions(Object status) {
		List<ActionMetadata> list = statusMachine.get(status);
		if (list == null) {
			return Collections.EMPTY_LIST;
		}
		return list;
	}

	public void addStatusAction(Object status, String action) {
		List<ActionMetadata> statusActions = statusMachine.get(status);
		if (statusActions == null) {
			statusActions = new ArrayList<ActionMetadata>();
			statusMachine.put(status, statusActions);
		}
		statusActions.add(actions.get(action));
		// ActionMetadata.sort(statusActions);
	}
}
